package conMgr.ui.papers;

import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.text.JTextComponent;

import conMgr.model.Paper;
import conMgr.model.Status;
import conMgr.model.User;
import conMgr.ui.util.SliderChangeListener;
import conMgr.ui.util.Ui;

/**
 * Provides a view a recommendation for a paper.
 * @author is4@uw.edu
 */
public class RecommendationView extends JPanel
{
	/**
	 * The serialization ID for this class. 
	 */
	private static final long serialVersionUID = 2277114900210176895L;

	/**
	 * The paper this recommendation is for.
	 */
	private final Paper paper;
	
	/**
	 * The ratings slider.
	 */
	private final JSlider ratingSlider;
	
	/**
	 * The rationale text box.
	 */
	private final JTextComponent rationaleTextBox;
	
	/**
	 * Initializes a new recommendation view.
	 * @param paper The paper this recommendation is for.
	 */
	public RecommendationView(final Paper paper)
	{
		this.paper = paper;
		
		setLayout(new GridBagLayout());
		
		addGridBagFieldLabel("Rating:", 0);
		addGridBagFieldLabel("Rationale:", 1);
		
		ratingSlider =
			addGridBagSlider(0, paper.getSubprogramChairRating() == null ? 3 : paper.getSubprogramChairRating());
		rationaleTextBox =
			addGridBagValueTextBox(1, paper.getSubprogramChairRationale(), true);
	}

	/**
	 * Adds a new field label to a grid bag.
	 * @param text The text to display in the label.
	 * @param row The row of the grid that the label belongs in.
	 */
	private void addGridBagFieldLabel(final String text, final int row)
	{
		final JLabel label = new JLabel(text);
		final GridBagConstraints constraints = new GridBagConstraints();
		constraints.gridx = 0;
		constraints.gridy = row;
		constraints.anchor = GridBagConstraints.NORTHWEST;
		constraints.insets = Ui.DEFAULT_INSETS;
		add(label, constraints);
	}
	
	/**
	 * Adds a new slider to a grid bag.
	 * @param row The row of the grid that the text box belongs in.
	 * @param value The value to display.
	 * @return The new slider.
	 */
	private JSlider addGridBagSlider(final int row, final int value)
	{
		final JSlider slider =
			new JSlider(JSlider.HORIZONTAL, 1, 5, value);
		slider.setMajorTickSpacing(1);
		slider.setMinorTickSpacing(1);
		slider.setPaintTicks(true);
		
		if
		(
			!(
				paper.getStatus() == Status.UNDECIDED ||
				paper.getStatus() == Status.RECOMMENDED
			) ||
			paper.getSubprogramChair() != User.getCurrentUser()
		)
			slider.setEnabled(false);
		
		GridBagConstraints constraints = new GridBagConstraints();
		constraints.gridx = 1;
		constraints.gridy = row;
		constraints.anchor = GridBagConstraints.WEST;
		constraints.insets = Ui.DEFAULT_INSETS;
		add(slider, constraints);
		
		final JLabel label = new JLabel(Integer.toString(slider.getValue()));
		constraints = new GridBagConstraints();
		constraints.gridx = 2;
		constraints.gridy = row;
		constraints.anchor = GridBagConstraints.WEST;
		constraints.insets = Ui.DEFAULT_INSETS;
		add(label, constraints);
		
		slider.addChangeListener(new SliderChangeListener(slider, label));
		
		return slider;
	}
	
	/**
	 * Adds a new empty text box to a grid bag.
	 * @param row The row of the grid that the text box belongs in.
	 * @param text The text to put in the text box.
	 * @return The newly-created text box.
	 */
	private JTextComponent addGridBagValueTextBox
	(
		final int row,
		final String text,
		boolean large
	)
	{
		JComponent addControl;
		JTextComponent field;
		
		if (large)
		{
			final JTextArea textArea = new JTextArea(text, 5, 30);
			textArea.setLineWrap(true);
			textArea.setWrapStyleWord(true);
			field = textArea;
			
			addControl = new JScrollPane(textArea);
		}
		else
			addControl = field = new JTextField(text, 30);
		
		if
		(
			!(
				paper.getStatus() == Status.UNDECIDED ||
				paper.getStatus() == Status.RECOMMENDED
			) ||
			paper.getSubprogramChair() != User.getCurrentUser()
		)
		{
			field.setEditable(false);
			field.setBackground(Color.WHITE);
		}
		
		final GridBagConstraints constraints = new GridBagConstraints();
		constraints.gridx = 1;
		constraints.gridwidth = 2;
		constraints.gridy = row;
		constraints.anchor = GridBagConstraints.NORTHWEST;
		constraints.fill = GridBagConstraints.HORIZONTAL;
		constraints.insets = Ui.DEFAULT_INSETS;
		add(addControl, constraints);
		
		return field;
	}
	
	/**
	 * Saves the recommendation, if applicable.
	 * @return True if no error was encountered; otherwise, false.
	 */
	public boolean save()
	{
		if (paper.getSubprogramChair() != User.getCurrentUser())
			return true;
		
		final Integer rating = ratingSlider.getValue();
		final String rationale = rationaleTextBox.getText();
		
		if (Ui.isBlank(rationale))
		{
			JOptionPane.showMessageDialog
			(
				null,
				"Please fill out all of the fields. A recommendation cannot be submitted with missing information.",
				"Cannot Submit Recommendation",
				JOptionPane.ERROR_MESSAGE
			);
			return false;
		}
		
		paper.submitToProgramChair(rating, rationale);
		return true;
	}
}
